Skip to content

MQTT/Protobuf Middleware API#390

Merged
bjackson312006 merged 14 commits intomqtt-ethernetfrom
mqtt-ethernet.protobuf-driver
Apr 7, 2026
Merged

MQTT/Protobuf Middleware API#390
bjackson312006 merged 14 commits intomqtt-ethernetfrom
mqtt-ethernet.protobuf-driver

Conversation

@bjackson312006
Copy link
Copy Markdown
Collaborator

@bjackson312006 bjackson312006 commented Apr 1, 2026

This PR implements a lightweight wrapper layer for message encoding that sits on top of the lower-level Ethernet/MQTT drivers. It's meant to provide a simple API that automatically handles encoding messages in the ServerData schema. This should ideally make it easier to set up Ethernet/MQTT/Protobuf in different repos.

The first function (technically a macro) in this API is nx_protobuf_mqtt_message_create(topic, unit, ...), which returns a message of type ethernet_mqtt_message_t. This function allows you to pass in a topic string literal, a unit string literal, and however many float datapoints you want (provided it doesn't exceed the maximum allowed). The lengths of the topic and unit strings, as well as the number of datapoints you pass into ..., are calculated automatically for you at compile time, so there's no risk of weird caller errors (i.e, forgetting to include a null terminator in the string size or something). The max/min length settings for the parameters (configured via PB_MAX_TOPIC_LENGTH, PB_MAX_UNIT_LENGTH, PB_MIN_DATAPOINTS, PB_MAX_DATAPOINTS) are also validated at compile-time, so if you violate any of the settings there, you will get a nice _Static_assert compiler error telling you exactly what rule you violated. TLDR the compiler will ensure you call this function correctly unless there's something I've forgotten about.

The second function in this API is nx_protobuf_mqtt_message_send(ethernet_mqtt_message_t* message), which dispatches a ethernet_mqtt_message_t object. If MQTT isn't connected, this function will try to reconnect indefinitely until MQTT has successfully been reconnected, either by this function directly or by another function/thread.

The intended application-layer workflow for this API looks kinda like this:
First, create a queue:

void vEthernet1Manager(ULONG thread_input) {

    ethernet_mqtt_message_t message = { 0 };

    while(1) {

        /* Send outgoing messages, recieve incoming messages */
        while(queue_receive(&eth_manager, &message, TX_WAIT_FOREVER) == U_SUCCESS) {
            int status = nx_protobuf_mqtt_message_send(&message);
            if(status != U_SUCCESS) {
                PRINTLN_ERROR("Failed to send outgoing mqtt ethernet message (Status: %d).", status);
            }
        }

        /* No sleep. Thread timing is controlled completely by the queue timeout. */
    }
}

Then, other threads can create messages and queue them, like this:

void vTest(ULONG thread_input) {

    while(1) {

        ethernet_mqtt_message_t message = nx_protobuf_mqtt_message_create("VCU_Ethernet/IMU/Acceleration", "unit", acceleration.x, acceleration.y, acceleration.z);
        queue_send(&eth_manager, &message, TX_NO_WAIT);

        tx_thread_sleep(test_thread.sleep);
    }
}

Some things of note:

  • I tested this on Cerberus-2.0, and everything worked except for PTP stuff. During my testing, ethernet_get_time() seemed to hang (right before the nx_ptp_client_time_get() call). The hanging did not occur for messages getting created in vTest, but did for messages getting created in vPeripherals. Kind of weird. I ended up commenting out the call to ethernet_get_time() within nx_protobuf_mqtt_message_create(), and just have time_us set to 10 (random number I chose).

@bjackson312006 bjackson312006 self-assigned this Apr 1, 2026
@bjackson312006 bjackson312006 changed the title experimenting with adding nanopb to embedded-base MQTT/Protobuf Middleware API Apr 2, 2026
@bjackson312006 bjackson312006 requested review from jr1221 and removed request for jr1221 April 2, 2026 02:44
@bjackson312006 bjackson312006 marked this pull request as ready for review April 6, 2026 02:24
@bjackson312006 bjackson312006 requested a review from jr1221 April 6, 2026 02:24
Copy link
Copy Markdown
Contributor

@jr1221 jr1221 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, one small question.

Comment thread NetX/inc/u_nx_protobuf.h
#define PB_STR_LEN(s) (sizeof(s) - 1) // Returns the length of a string literal.

/* CONFIG: Compile-time validation of topic size, unit size, and number of values. */
#define PB_MAX_TOPIC_LENGTH 100 // Maximum length of topic string literal (in characters).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this exposed somewhere in the generated serverdata.h? That way we dont need to hardcode it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None are afaik, they seem to be hardcoded without macros. The MQTT topic length is technically something just in the mqtt layer rather than protobuf but we have to hardcode it somewhere

@bjackson312006 bjackson312006 merged commit 0df5a19 into mqtt-ethernet Apr 7, 2026
1 of 2 checks passed
@bjackson312006 bjackson312006 deleted the mqtt-ethernet.protobuf-driver branch April 7, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants